//build：20240315
//Some common functions, constants, enumerations, etc.
import { uiClass } from '../dxmodules/libvbar-m-dxui.so'
const ui = new uiClass();
// Initialize UI components
ui.init()

let utils = {}
utils.GG = NativeObject.APP.NativeComponents
utils.ENUM = utils.GG.NativeEnum
utils.LAYER = {
    "MAIN": 0,
    "SYS": 1,
    "TOP": 2
}
utils.EVENT = {
    "CLICK": 7,
    "LONG_PRESSED": 5,
    "SHORT_PRESSED": 4,
    "PRESSING": utils.ENUM.LV_EVENT_PRESSING,
    "FOCUSED": utils.ENUM.LV_EVENT_FOCUSED,
    "DEFOCUSED": utils.ENUM.LV_EVENT_DEFOCUSED,
    "VALUE_CHANGED": utils.ENUM.LV_EVENT_VALUE_CHANGED,
    "INSERT": utils.ENUM.LV_EVENT_INSERT,
    "REFRESH": utils.ENUM.LV_EVENT_REFRESH,
    "READY": utils.ENUM.LV_EVENT_READY,
    "CANCEL": utils.ENUM.LV_EVENT_CANCEL,
}
utils.TEXT_ALIGN = {
    "AUTO": 0,
    "LEFT": 1,
    "CENTER": 2,
    "RIGHT": 3
}
utils.STATE = {
    "DEFAULT": utils.ENUM.LV_STATE_DEFAULT,
    "CHECKED": utils.ENUM.LV_STATE_CHECKED,
    "FOCUSED": utils.ENUM.LV_STATE_FOCUSED,
    "FOCUS_KEY": utils.ENUM.LV_STATE_FOCUS_KEY,
    "EDITED": utils.ENUM.LV_STATE_EDITED,
    "HOVERED": utils.ENUM.LV_STATE_HOVERED,
    "PRESSED": utils.ENUM.LV_STATE_PRESSED,
    "SCROLLED": utils.ENUM.LV_STATE_SCROLLED,
    "DISABLED": utils.ENUM.LV_STATE_DISABLED,
}
utils.OBJ_FLAG = {
    "CLICKABLE": utils.ENUM.LV_OBJ_FLAG_CLICKABLE,
}
utils.ALIGN = {//The position relative to the reference object, marked with OUT, is outside the boundary of the reference object.
    "OUT_TOP_LEFT": utils.ENUM.LV_ALIGN_OUT_TOP_LEFT,
    "OUT_TOP_MID": utils.ENUM.LV_ALIGN_OUT_TOP_MID,
    "OUT_TOP_RIGHT": utils.ENUM.LV_ALIGN_OUT_TOP_RIGHT,
    "OUT_BOTTOM_LEFT": utils.ENUM.LV_ALIGN_OUT_BOTTOM_LEFT,
    "OUT_BOTTOM_MID": utils.ENUM.LV_ALIGN_OUT_BOTTOM_MID,
    "OUT_BOTTOM_RIGHT": utils.ENUM.LV_ALIGN_OUT_BOTTOM_RIGHT,
    "OUT_LEFT_TOP": utils.ENUM.LV_ALIGN_OUT_LEFT_TOP,
    "OUT_LEFT_MID": utils.ENUM.LV_ALIGN_OUT_LEFT_MID,
    "OUT_LEFT_BOTTOM": utils.ENUM.LV_ALIGN_OUT_LEFT_BOTTOM,
    "OUT_RIGHT_TOP": utils.ENUM.LV_ALIGN_OUT_RIGHT_TOP,
    "OUT_RIGHT_MID": utils.ENUM.LV_ALIGN_OUT_RIGHT_MID,
    "OUT_RIGHT_BOTTOM": utils.ENUM.LV_ALIGN_OUT_RIGHT_BOTTOM,
    "TOP_LEFT": utils.ENUM.LV_ALIGN_TOP_LEFT,
    "TOP_MID": utils.ENUM.LV_ALIGN_TOP_MID,
    "TOP_RIGHT": utils.ENUM.LV_ALIGN_TOP_RIGHT,
    "BOTTOM_LEFT": utils.ENUM.LV_ALIGN_BOTTOM_LEFT,
    "BOTTOM_MID": utils.ENUM.LV_ALIGN_BOTTOM_MID,
    "BOTTOM_RIGHT": utils.ENUM.LV_ALIGN_BOTTOM_RIGHT,
    "LEFT_MID": utils.ENUM.LV_ALIGN_LEFT_MID,
    "RIGHT_MID": utils.ENUM.LV_ALIGN_RIGHT_MID,
    "CENTER": utils.ENUM.LV_ALIGN_CENTER,
    "DEFAULT": utils.ENUM.LV_ALIGN_DEFAULT
}
utils.FLEX_ALIGN = {//Flexbox layout, alignment
    "START": utils.ENUM.LV_FLEX_ALIGN_START,
    "END": utils.ENUM.LV_FLEX_ALIGN_END,
    "CENTER": utils.ENUM.LV_FLEX_ALIGN_CENTER,
    "SPACE_EVENLY": utils.ENUM.LV_FLEX_ALIGN_SPACE_EVENLY,
    "SPACE_AROUND": utils.ENUM.LV_FLEX_ALIGN_SPACE_AROUND,
    "SPACE_BETWEEN": utils.ENUM.LV_FLEX_ALIGN_SPACE_BETWEEN,
}
utils.FLEX_FLOW = {//Flexbox layout, main and cross axes
    "ROW": utils.ENUM.LV_FLEX_FLOW_ROW,
    "COLUMN": utils.ENUM.LV_FLEX_FLOW_COLUMN,
    "ROW_WRAP": utils.ENUM.LV_FLEX_FLOW_ROW_WRAP,
    "ROW_REVERSE": utils.ENUM.LV_FLEX_FLOW_ROW_REVERSE,
    "ROW_WRAP_REVERSE": utils.ENUM.LV_FLEX_FLOW_ROW_WRAP_REVERSE,
    "COLUMN_WRAP": utils.ENUM.LV_FLEX_FLOW_COLUMN_WRAP,
    "COLUMN_REVERSE": utils.ENUM.LV_FLEX_FLOW_COLUMN_REVERSE,
    "COLUMN_WRAP_REVERSE": utils.ENUM.LV_FLEX_FLOW_COLUMN_WRAP_REVERSE,
}
utils.GRAD = {//Gradient direction
    "NONE": utils.ENUM.LV_GRAD_DIR_NONE,
    "VER": utils.ENUM.LV_GRAD_DIR_VER,
    "HOR": utils.ENUM.LV_GRAD_DIR_HOR,
}
utils.KEYBOARD = {//Keyboard mode
    "TEXT_LOWER": utils.ENUM.LV_KEYBOARD_MODE_TEXT_LOWER,
    "TEXT_UPPER": utils.ENUM.LV_KEYBOARD_MODE_TEXT_UPPER,
    "SPECIAL": utils.ENUM.LV_KEYBOARD_MODE_SPECIAL,
    "NUMBER": utils.ENUM.LV_KEYBOARD_MODE_NUMBER,
    "K26": "K26",
    "K9": "K9",
}
utils.FONT_STYLE = {
    "NORMAL": utils.ENUM.FT_FONT_STYLE_NORMAL,
    "ITALIC": utils.ENUM.FT_FONT_STYLE_ITALIC,
    "BOLD": utils.ENUM.FT_FONT_STYLE_BOLD,
}
utils.BUTTONS_STATE = {
    "HIDDEN": utils.ENUM.LV_BTNMATRIX_CTRL_HIDDEN,//Whether a button in the button matrix is ​​hidden.
    "NO_REPEAT": utils.ENUM.LV_BTNMATRIX_CTRL_NO_REPEAT,//Can the buttons in the button matrix be pressed repeatedly without triggering the key event repeatedly?
    "DISABLED": utils.ENUM.LV_BTNMATRIX_CTRL_DISABLED,//Whether a button in the button matrix is ​​disabled.
    "CHECKABLE": utils.ENUM.LV_BTNMATRIX_CTRL_CHECKABLE,//Can the buttons in the button matrix be selected?
    "CHECKED": utils.ENUM.LV_BTNMATRIX_CTRL_CHECKED,//Whether a button in the button matrix is ​​selected is displayed as selected on the interface.
    "CLICK_TRIG": utils.ENUM.LV_BTNMATRIX_CTRL_CLICK_TRIG,//Can the buttons in the button matrix be triggered by clicking?
    "POPOVER": utils.ENUM.LV_BTNMATRIX_CTRL_POPOVER,//Does a button in the matrix pop up, and will clicking it reveal more options or content?
    "RECOLOR": utils.ENUM.LV_BTNMATRIX_CTRL_RECOLOR//Can the buttons in the matrix be recolored?
}
//The part where the style takes effect
utils.STYLE_PART = {
    "MAIN": 0, //The current style of the object is in effect.
    "ITEMS": 327680//The inner items of an object take effect, such as the button group in buttonMatrix.
}
//Text exceeds the control's display mode.
utils.LABEL_LONG_MODE = {
    "WRAP": utils.ENUM.LV_LABEL_LONG_WRAP,//Line breaks when text is long
    "DOT": utils.ENUM.LV_LABEL_LONG_DOT,//Use "..." to replace long text.
    "SCROLL": utils.ENUM.LV_LABEL_LONG_SCROLL,//Automatic scrolling when the text is long
    "SCROLL_CIRCULAR": utils.ENUM.LV_LABEL_LONG_SCROLL_CIRCULAR,//Scrolling through long texts
    "CLIP": utils.ENUM.LV_LABEL_LONG_CLIP,//Automatically truncate long texts
}
// To map 0-100 to 0-255
utils.OPA_MAPPING = function (value) {
    return Math.round((value / 100) * 255);
}
/**
* Check if the number is empty, or if it is a number.
* @param {number} n Required
* @param {err} Error message, optional, but filling it in will throw an Error.
*/
utils.validateNumber = function (n, err) {
    return _valid(n, 'number', err)
}
/**
* Validate whether the object is empty or an object.
* @param {object} o Required
* @param {err} Error message, optional, but filling it in will throw an Error.
*/
utils.validateObject = function (o, err) {
    return _valid(o, 'object', err)
}
/**
 * Validate the construction parameters of the UI object
 * @param {array} all Required, all object references
 * @param {string} id Cannot be empty, required.
 * @param {object} parent Optional, default value is 0
 */
utils.validateBuild = function (all, id, parent, type) {
    this.validateId(all, id)
    if (parent === 0 || parent === 1 || parent === 2) {
        return parent
    }
    if (!parent || !parent.obj) {
        throw new Error(type + ".build: 'parent' paramter should not be null")
    }
    return parent.obj
}
/**
 * Validate the IDs of all UI controls to ensure they are not duplicated.
 * @param {array} all 
 * @param {string} id 
 */
utils.validateId = function (all, id) {
    this.validateString(id, "The 'id' parameter should not be null.")
    if (all[id]) {
        throw new Error("The id(" + id + ") already exists. Please set a different id value.")
    }
}
/**
* Check if a string is empty
* @param {string} s Required
* @param {err} Error message, optional, but filling it in will throw an Error.
*/
utils.validateString = function (s, err) {
    let res = _valid(s, 'string', err)
    if (!res) {
        return false
    }
    if (s.length <= 0) {
        if (err) {
            throw new Error(err)
        }
        return false
    }
    return true
}
/**
 * Analyzing different types of color values
 * @param {any} value Supported numeric type: '0x34ffaa', string type: '0x34ffaa', string type: '#34ffaa'
 * @returns 
 */
utils.colorParse = function (value) {
    if (typeof value == 'string') {
        value = value.replace('#', '0x')
        value = parseInt(value, 16)
    }
    return value
}
/**
 * Get the coordinates of the touch point
 * @returns {x: x-coordinate, y: y-coordinate}
 */
utils.getTouchPoint = function () {
    let point = NativeObject.APP.NativeComponents.NativeIndev.lvIndevGetPoint()
    return point
}
/**
 * Provide animation
 * @param {object} obj The animation operation object can be any object; callback parameters are retrieved.
 * @param {number} start The start value of the interval is generally used in conjunction with end, and is obtained as a callback parameter. The start value changes to the end value during the animation.
 * @param {number} end Interval end value
 * @param {function} cb The callback function (obj, v) => {}, where obj is the animation operation object, and the range is (start-end).
 * @param {number} duration Animation duration, milliseconds
 * @param {number} backDuration Optional, animation playback time, milliseconds; default is no playback.
 * @param {number} repeat Optional, number of animation repetitions, default is 1 time.
 * @param {string} mode Rate curve, optional, default is linear, built-in functions: linear, ease_in, ease_out, ease_in_out, overshoot, bounce, step
 *  linear animation
    step changes in the last step
    ease_in starts slowly
    ease_out ends slowly
    ease_in_out is slow at both the beginning and end
    overshoot exceeds the final value
    bounce bounces slightly from the final value (e.g., hitting a wall)
 * @returns Animation instances must be saved globally.
 */
utils.anime = function (obj, start, end, cb, duration, backDuration, repeat, mode) {
    // 1. Initialize animation
    let anim = NativeObject.APP.NativeComponents.NativeAnim.lvAnimInit()
    // 2. Set the animation object
    anim.lvAnimSetVar(obj)
    // 3. Set start and end values
    anim.lvAnimSetValues(start, end)
    // 4. Set animation callback function
    anim.lvAnimSetExecCb(cb)
    // 5. Set animation time
    anim.lvAnimSetTime(duration)
    // Optional: Set the animation playback time. If not set, the animation will not play.
    if (backDuration) {
        anim.lvAnimSetPlaybackTime(backDuration)
    }
    // Optional, set the number of times the animation repeats.
    if (repeat) {
        anim.lvAnimSetRepeatCount(repeat)
    }
    // Optional, set the animation speed curve
    if (mode) {
        anim.lvAnimSetPathCb(mode)
    }
    // 6. Run the animation
    anim.lvAnimStart()
    return anim
}
// Each object has a parent and children set.
utils.setParent = function (all, child, parent) {
    if (!all || parent == null || parent == undefined || !child) {
        return
    }
    if((typeof parent)=='number'){

    }
    const parentId = ((typeof parent)=='number')?'' + parent:parent.id// Convert 0, 1, 2 into strings
    if (!all[parentId]) {
        all[parentId] = { id: parentId }// Root node 0,1,2
    }
    if (!all[parentId].children) {
        all[parentId].children = []
    }
    all[parentId].children.push(child.id)
    child.parent = parentId
    all[child.id] = child
}
function _valid(n, type, err) {
    if (n === undefined || n === null || (typeof n) != type) {
        if (err) {
            throw new Error(err)
        }
        return false
    }
    return true
}
export default utils